import { useMutation } from "react-relay";
import {useCallback, useState} from "react";
import {RecordProxy, RecordSourceSelectorProxy,} from "relay-runtime";
import {useToast} from "customize-easy-ui-component";
import {useNewReportMutation$data} from "./__generated__/useNewReportMutation.graphql"
import {useDeleteReportMutation$data} from "./__generated__/useDeleteReportMutation.graphql";
const graphql = require("babel-plugin-relay/macro");

/**新建立task: 必须最少有个设备？(无关联设备号的单独报告的任务？)
先生成task后面再来添加eqp;
Mutation必须能够返回被变更影响到的并且前端数据一致性很重要的的关联对象，尽量满足前端需求驱动=直接关联页面数据一致性。
type  MarkAllTodosPayload {
  changedTodos: [Todo!]
  user: User!   }
type  AddTodoPayload {
  todoEdge: TodoEdge!
  user: User!   }
分项报告和收费项目没有必然联系；派工环节Task任务负责人自己决定是否增加哪些分项报告。
 任务负责人dispatchTaskTo给校核人检验人员审核人审批人。默认的分项采取和主报告(dispatchTaskTo:TASK初始化时就有生成的主报告)主报告相一致的人员配备的。
 后续的，任务负责人可以增加分项报告同时配置人员参数。
 任务责任人dispatchTaskTo(taskDate: Date）这个操作应当是距离真正的检验工作日期非常接近的日子去做。
 任务责任人才有权利执行newReport｛主报告或分项报告以及人员配置甚至收费项目参数设置的｝
* */
const mutation = graphql`
  mutation useNewReportMutation(
    $isp: ID!, $master:ID, $ispMens:[ID], $reviewer:ID,
    $approver:ID, $type: String!,  $version: Int!
  ) {
     newReport(isp: $isp, master:$master,ispMens:$ispMens,reviewer:$reviewer,approver:$approver, modeltype: $type, modelversion: $version) {
       #光光直接返回一个Report不见得足够了，Relay有可能需要在包裹一层附带返回其它受到影响的东西: {},{}
      id, upLoadDate, isp{id,no}
    }
  }
`;

let tempID = 1;   //临时生成客户端自己的id，随后后端应答就被替换

export default function useNewReportMutation() {
  const [called, setCalled] =useState<boolean>(false);
  const [result, setResult] =useState<useNewReportMutation$data |undefined>();
  const [commit, doing] = useMutation(mutation);
  const toast = useToast();
  return {
    call:useCallback(
      (isp: string, master: string, ispMens: string[],reviewer: string,approver: string,type: string, version: number) => {
        let disposable= commit({
          variables: {
            isp,master, ispMens, reviewer,approver, type, version
          },
          updater: (store: RecordSourceSelectorProxy, data) => {
            const payload = store.getRootField("newReport");
            if (!payload) {
              return;
            }
            sharedUpdater(store, isp, payload);
          },
          optimisticUpdater: (store: RecordSourceSelectorProxy) => {
            const id = "client:" + tempID++;
            const node = store.create(id, "SimpleReport");
            node.setValue(id, "id");
            node.setValue('临时?', "no");
            node.setValue('未知2', "upLoadDate");
            sharedUpdater(store, isp, node);
          },
          onCompleted: (response) => {
            setResult(response as any);
            console.log("跑到useBuildTaskMutation2输出=", response);
            toast({
              title: "生成任务应答",
              subtitle: '新Task的ID＝'+ (response as any).newReport.id,
              intent: "info"
            });
          },
          onError: error => {
            toast({title: "后端回答",subtitle: ""+error, intent: "warning"});
          }
        });
        //必须放在commit函数之后的，才会doing逻辑=true生效,doing+called逻辑,保障同步化
        setCalled(true);
        return disposable;
      },
      [commit,toast]
    ),
    doing,
    result,
    called,
    reset: ()=>setCalled(false),
  };
}

/**普通的【】数组列表 原始操作做模式； 另外一种是 Connetion 模式对List<Set>比这个模式简单点的。
 * */
function sharedUpdater(
    store: RecordSourceSelectorProxy,
    ispId: string,
    newNode: RecordProxy
) {
  const payload =store.get(ispId);
  if(!payload)  return;
  //这种方式，普通的【】数组列表也能做。就是要确定list链接于哪一个父辈对象{list:[]?}底下的，挂接父辈ID链接;根路径Query{}只能重查了;
  const payloadreps = payload.getLinkedRecord("reps");
  const payloadrepsedges = payloadreps?.getLinkedRecords("edges");

  const newEdge = store.create(
      "client:newEdge:" + tempID++,
      "SimpleReportConnectionEdge"
  );
  newEdge.setLinkedRecord(newNode, "node");

  const newarredge= payloadrepsedges?.concat(newEdge);
  payloadreps?.setLinkedRecords(newarredge,"edges");
}

